﻿using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using System.Web;

namespace IceDog.WebApi.AnythingApi.Utils
{
    /// <summary>
    /// 
    /// </summary>
    public static class WebHelper
    {
        private static string userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36";
        private static int timeout = 60000;
        private static IHttpContextAccessor _accessor;

        /// <summary>
        /// 设置 http 上下文访问器
        /// </summary>
        /// <param name="accessor"></param>
        public static void SetHttpContextAccessor(IHttpContextAccessor accessor)
        {
            _accessor = accessor;
        }
        /// <summary>
        /// 获取当前请求的源， 如 http://172.16.2.24:100
        /// </summary>
        /// <returns></returns>
        public static string GetOrigin()
        {
            var req = _accessor.HttpContext.Request;
            var origin = $"{req.Scheme}://{req.Host}";
            return origin;
        }

        /// <summary>
        /// 获取当前的请求对象
        /// </summary>
        /// <returns></returns>
        public static HttpRequest GetRequest()
        {
            var req = _accessor.HttpContext.Request;
            return req;
        }

        /// <summary>
        /// 获取当前的请求对象的 cookie
        /// </summary>
        /// <returns></returns>
        public static IRequestCookieCollection GetCookies()
        {
            var req = _accessor.HttpContext.Request;
            var cookies = req.Cookies;
            return cookies;
        }

        public static void HttpWebRequestBuilder()
        {

        }

        /// <summary>
        /// 发起Get请求
        /// </summary>
        /// <returns></returns>
        public static void Get(string url,Dictionary<string,string> args,ref string res)
        {

        }

        public static HttpWebResponse CreatePostHttpResponseForJson(string url, string jsonStr, int timeout, string userAgent, Encoding requestEncoding, ref string responseInfo)
        {
            try
            {
                if (string.IsNullOrEmpty(url))
                {
                    throw new ArgumentNullException("url");
                }
                if (requestEncoding == null)
                {
                    throw new ArgumentNullException("requestEncoding");
                }
                HttpWebRequest request = null;
                //如果是发送HTTPS请求
                if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
                {
                    ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
                    request = WebRequest.Create(url) as HttpWebRequest;
                    request.ProtocolVersion = HttpVersion.Version10;
                }
                else
                {
                    request = WebRequest.Create(url) as HttpWebRequest;
                }
                request.Headers.Add("X-Origin-Request-IP", GetRequestIP());
                request.Method = "POST";
                request.ContentType = "application/json";
                request.Timeout = timeout;
                if (!string.IsNullOrEmpty(userAgent))
                {
                    request.UserAgent = userAgent;
                }
                byte[] data = requestEncoding.GetBytes(jsonStr);
                using (Stream stream = request.GetRequestStream())
                {
                    stream.Write(data, 0, data.Length);
                }

                HttpWebResponse webresponse = request.GetResponse() as HttpWebResponse;
                using (StreamReader reader = new StreamReader(webresponse.GetResponseStream(), requestEncoding))
                {
                    responseInfo = reader.ReadToEnd();
                }
                return webresponse;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 创建POST方式的HTTP请求
        /// </summary>
        /// <param name="url">请求的URL</param>
        /// <param name="requestParameters">请求参数</param>
        /// <param name="timeout">请求的超时时间</param>
        /// <param name="userAgent">请求的客户端浏览器信息，可以为空</param>
        /// <param name="requestEncoding">发送HTTP请求时所用的编码</param>
        /// <param name="responseInfo">返回请求结果</param>
        /// <returns></returns>
        public static HttpWebResponse CreatePostHttpResponse(string url, IDictionary<string, string> requestParameters, int timeout,
            string userAgent, Encoding requestEncoding, ref string responseInfo, string contentType = "", Dictionary<string, object> fileParameters = null, Dictionary<string, string> cookies = null)
        {
            try
            {
                if (string.IsNullOrEmpty(url))
                {
                    throw new ArgumentNullException("url");
                }
                if (requestEncoding == null)
                {
                    throw new ArgumentNullException("requestEncoding");
                }
                HttpWebRequest request = null;
                //如果是发送HTTPS请求
                if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
                {
                    ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
                    request = WebRequest.Create(url) as HttpWebRequest;
                    request.ProtocolVersion = HttpVersion.Version10;
                }
                else
                {
                    request = WebRequest.Create(url) as HttpWebRequest;
                }
                request.Headers.Add("X-Origin-Request-IP", GetRequestIP());
                request.Method = "POST";
                request.ContentType = string.IsNullOrEmpty(contentType) ? "application/x-www-form-urlencoded" : contentType;
                request.Timeout = timeout;
                if (cookies != null)
                {
                    request.CookieContainer = new CookieContainer();
                    foreach (var key in cookies.Keys)
                    {
                        var value = cookies[key];
                        request.CookieContainer.Add(new Cookie(key, value, "/", GetRequestIP()));
                    }
                }
                if (!string.IsNullOrEmpty(userAgent))
                {
                    request.UserAgent = userAgent;
                }
                //如果需要POST数据
                if (!(requestParameters == null || requestParameters.Count == 0))
                {
                    byte[] data = null;
                    if (contentType.ToLower() != "application/json")
                    {
                        StringBuilder buffer = new StringBuilder();
                        int i = 0;
                        foreach (string key in requestParameters.Keys)
                        {
                            if (i > 0)
                            {
                                buffer.AppendFormat("&{0}={1}", key, HttpUtility.UrlEncode(requestParameters[key]));
                            }
                            else
                            {
                                buffer.AppendFormat("{0}={1}", key, HttpUtility.UrlEncode(requestParameters[key]));
                            }
                            i++;
                        }
                        data = requestEncoding.GetBytes(buffer.ToString());
                    }
                    else
                    {
                        var jsonText = JsonSerializer.Serialize(requestParameters);
                        data = requestEncoding.GetBytes(jsonText);
                    }


                    using (Stream stream = request.GetRequestStream())
                    {
                        stream.Write(data, 0, data.Length);
                    }
                }
                else if (fileParameters != null && fileParameters.Any())
                {
                    string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
                    byte[] boundaryBytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
                    request.ContentType = "multipart/form-data; boundary=" + boundary;

                    using (Stream stream = request.GetRequestStream())
                    {
                        foreach (KeyValuePair<string, object> pair in fileParameters)
                        {
                            stream.Write(boundaryBytes, 0, boundaryBytes.Length);
                            if (pair.Value is FileInfo)
                            {
                                var file = pair.Value as FileInfo;
                                string header = "Content-Disposition: form-data; name=\"" + pair.Key + "\"; filename=\"" + file.Name + "\"\r\nContent-Type: " + contentType + "\r\n\r\n";
                                byte[] bytes = System.Text.Encoding.UTF8.GetBytes(header);
                                stream.Write(bytes, 0, bytes.Length);
                                byte[] buffer = new byte[32768];
                                int bytesRead;
                                // upload from file
                                using (var fileStream = file.OpenRead())
                                {
                                    while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
                                        stream.Write(buffer, 0, bytesRead);
                                    fileStream.Close();
                                }
                            }
                            else
                            {
                                string data = "Content-Disposition: form-data; name=\"" + pair.Key + "\"\r\n\r\n" + pair.Value;
                                byte[] bytes = System.Text.Encoding.UTF8.GetBytes(data);
                                stream.Write(bytes, 0, bytes.Length);
                            }
                        }
                        boundaryBytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
                        stream.Write(boundaryBytes, 0, boundaryBytes.Length);
                    }
                }

                HttpWebResponse webresponse = request.GetResponse() as HttpWebResponse;
                using (StreamReader reader = new StreamReader(webresponse.GetResponseStream(), requestEncoding))
                {
                    responseInfo = reader.ReadToEnd();
                }
                return webresponse;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 创建GET方式的HTTP请求
        /// </summary>
        /// <param name="url">请求的URL</param>
        /// <param name="timeout">请求的超时时间</param>
        /// <param name="userAgent">请求的客户端浏览器信息，可以为空</param>
        /// <param name="requestEncoding">发送HTTP请求时所用的编码</param>
        /// <param name="responseInfo">返回请求结果</param>
        /// <returns></returns>
        public static HttpWebResponse CreateGetHttpResponse(string url, int timeout, string userAgent, Encoding requestEncoding, ref string responseInfo, string contentType = "")
        {
            try
            {
                if (string.IsNullOrEmpty(url))
                {
                    throw new ArgumentNullException("url");
                }
                if (requestEncoding == null)
                {
                    throw new ArgumentNullException("requestEncoding");
                }
                HttpWebRequest request = null;
                //如果是发送HTTPS请求
                if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
                {
                    ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
                    request = WebRequest.Create(url) as HttpWebRequest;
                    request.ProtocolVersion = HttpVersion.Version10;
                }
                else
                {
                    request = WebRequest.Create(url) as HttpWebRequest;
                }
                request.Headers.Add("X-Origin-Request-IP", GetRequestIP());
                request.Method = "GET";
                request.ContentType = string.IsNullOrEmpty(contentType) ? "application/x-www-form-urlencoded" : contentType;
                request.Timeout = timeout;
                request.UserAgent = userAgent;
                if (!string.IsNullOrEmpty(userAgent))
                {
                    request.UserAgent = userAgent;
                }

                HttpWebResponse webresponse = request.GetResponse() as HttpWebResponse;
                using (StreamReader reader = new StreamReader(webresponse.GetResponseStream(), requestEncoding))
                {
                    responseInfo = reader.ReadToEnd();
                }
                return webresponse;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public static string GetRequestIP()
        {
            string ip = "";
            try
            {
                ip = _accessor.HttpContext.Request.Headers["X-Origin-Request-IP"].FirstOrDefault();
                if (string.IsNullOrEmpty(ip))
                {
                    ip = _accessor.HttpContext.Request.Headers["X-Forwarded-For"].FirstOrDefault();
                }
                if (string.IsNullOrEmpty(ip))
                {
                    ip = _accessor.HttpContext.Request.Headers["X-Real-IP"].FirstOrDefault();
                }
                if (string.IsNullOrEmpty(ip))
                {
                    ip = _accessor.HttpContext.Connection.RemoteIpAddress.ToString();
                }

                if (ip.Contains(","))
                {
                    ip = ip.Replace(" ", "");
                    ip = ip.Split(",")[0];
                }
            }
            catch
            {

            }

            return ip;
        }

        private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        {
            return true; //总是接受
        }
    }
}
